package brain;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import logger.Logger;
import model.DrawCommand;
import model.Sorter;
import model.SorterFactory;
import model.Sorters;
import model.Statistics;
import simulation.VisualEngine;
import simulation.Visualizer;
import view.Runner;
import view.View;

/**
 * @author  Owner
 */
@SuppressWarnings("unchecked")
public class SortManager {
    private SorterFactory sorterFactory;

    private VisualEngine visualEngine;

    Thread simulationThread;
    
    /**
	 * @uml.property  name="statistics"
	 * @uml.associationEnd  multiplicity="(0 -1)"
	 */
    Statistics[] statistics;

    private static SortManager sortManager;

    public static SortManager getInstance() {
	if (sortManager == null) {
	    sortManager = new SortManager();
	}
	return sortManager;
    }

    private SortManager() {
	sorterFactory = SorterFactory.getInstance();
	statistics = new Statistics[Sorters.values().length];
    }

	public void manageSort(Comparable[] workArray, boolean[] simulationArray) {
	Comparable[] workArrayCpy = workArray.clone();
	Queue<DrawMemory> BigQueue = new LinkedList<DrawMemory>();
	boolean simulationFlag = false;

	for (int i = 0; i < Sorters.values().length; i++) {
	    Comparable[] workArrayCpy2 = workArrayCpy.clone();

	    Sorter sorter = sorterFactory.getSorter(Sorters.values()[i]);

	    if (simulationArray[i]) {
		ArrayBlockingQueue<DrawCommand> queue = new ArrayBlockingQueue<DrawCommand>(
			sorter.getComplexity(workArray.length));
		sorter.setQueue(queue);
		String sortType = "";

		switch (i) {
		case Sorter.SELECTION:
		    sortType = "Selection Sort";
		    break;
		case Sorter.BUBBLE:
		    sortType = "Bubble Sort";
		    break;
		case Sorter.SHELL:
		    sortType = "Shell Sort";
		    break;
		case Sorter.INSERTION:
		    sortType = "Insertion Sort";
		    break;
		case Sorter.MERGE:
		    sortType = "Merge Sort";
		    break;
		case Sorter.QUICK:
		    sortType = "Quick Sort";
		    break;

		case Sorter.HEAP:
		    sortType = "Heap Sort";
		    break;

		default:
		    break;
		}
		sorter.setSimulated(true);
		BigQueue.add(new DrawMemory(queue, sortType));
		simulationFlag = true;
	    }
	    sorter.sort(workArrayCpy2); // get array from array source
	    statistics[i] = sorter.getStatistics();
	}
		if (simulationFlag) {
			Runner.getInstance().setSimMode(true);
			Integer[] temp = new Integer[workArray.length];
			for (int i = 0; i < workArrayCpy.length; i++) {
				temp[i] = (Integer) workArrayCpy[i];
			}
			Visualizer visualizer = Visualizer.getInstance();

			visualEngine = new VisualEngine(temp, BigQueue, visualizer);
			simulationThread = new Thread(visualEngine);
			simulationThread.start();
		} else {
			Logger.showInfoMessage(View.getInstance().getShell(), "        No Simulation Selected        ");
		}
    }

    public Statistics[] getStatisticsArray() {
	return statistics;
    }
    
    @SuppressWarnings("deprecation")
    public void stopSimulation(){
	simulationThread.stop();
	Runner.getInstance().setSimMode(false);
    }
    
    public  void pauseSimulation() {
	visualEngine.pause();
    }
    
    public  void resumeSimulation() {
	visualEngine.resume();
    }
    
    public  void skipSimulation() {
	visualEngine.skip();
    }
}
